package com.tmzn.rewrite.service;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.tmzn.mapper.TDeviceRecordMapper;
import com.tmzn.rewrite.entity.PhpMap;
import com.tmzn.rewrite.entity.ResultMsg;
import com.tmzn.rewrite.util.PhpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 重写php相关的逻辑
 */
@Service
@Slf4j
public class FeeService {

    @Autowired
    private TDeviceRecordMapper tDeviceRecordMapper;

    public ResultMsg refund(PhpMap $_GPC) {
        PhpMap $gloable= new PhpMap();
        String msg = "";
        boolean status = false;
        Integer $plid = $_GPC.get("plid");
        if (isEmpty($plid)) {
            msg = "error param";
            return ResultMsg.fail(msg);
        }
        Integer $query_ts = $_GPC.get("query_ts");
        if(isEmpty($query_ts)){
            msg = "error param";
            return ResultMsg.fail(msg);
        }
        String $core_paylog_tab_cur = PhpUtil.getPayLogTable($query_ts);

        PhpMap $paylog = findOne("SELECT plid, status, openid, type, createtime, tid, fee, dev_id, refund_type, refund_id, refund_fee, endtime, is_recharge,tag  FROM " + $core_paylog_tab_cur + " where plid = " + $plid + "");

        if (empty($paylog.get("plid")) || empty($paylog.get("status"))){
            return ResultMsg.fail("订单未找到");
        }
        Object tag = $paylog.get("tag");
        String type = $paylog.get("type");
        if (!"wechat".equals(type) && !"alipay".equals(type)){
            return ResultMsg.fail("不支持退款");
        }

        Integer dev_id = $paylog.getInt("dev_id");
        if (empty(dev_id)) {
            return ResultMsg.fail("未绑定设备");
        }



        //不做判断权限
//        if ($paylog.get("tid") != $operator_uid){
//            return ResultMsg.fail("没有操作权限");
//        }

        //取消3天时间
//        if ($paylog.get("createtime") < strtotime("-3 days")) {
//            return ResultMsg.fail("已超过原路退款时效");
//        }
        Integer $operator_uid = $paylog.get("tid");
        PhpMap $withdraw_record = findOne("SELECT id, createtime, status FROM ims_core_withdrawlog WHERE uid="+$operator_uid+" ORDER by id DESC LIMIT 1");

        if(!empty($withdraw_record)){
            if (empty($withdraw_record.get("status"))) {
                int createtimeTimestamp = $withdraw_record.getInt("createtime");
                int nowTime = PhpUtil.getTimeSeconds();
                int gap = nowTime - createtimeTimestamp;
                // 现在我们可以将这个时间戳与当前时间往前推3分钟的时刻进行比较
                if(gap<180){
                    return ResultMsg.fail("当前有未完成的提现,请在提现完成后再操作");
                }
            }
        }


        Integer refund_type = $paylog.getInt("refund_type");
        String $refund_tab = PhpUtil.getRefundLogTable();
        PhpMap $refund_log = new PhpMap();
        if (!empty(refund_type)) {
            Integer refund_id = $paylog.getInt("refund_id");
            $refund_log = findOne("SELECT * FROM "+$refund_tab+" WHERE id="+refund_id);
            if (empty($refund_log)) {
                $refund_tab = PhpUtil.getRefundLogTableLastMonth();
                $refund_log =findOne("SELECT * FROM "+$refund_tab+" WHERE id="+refund_id);
            }
            if (empty($refund_log)) {
                return ResultMsg.fail("订单已超过原路退款时效");
            }
            Boolean refundStatus = $refund_log.get("status");
            if (refundStatus) {
                return ResultMsg.fail("订单已退款");
            }
        }


        Double $refund_fee = $_GPC.getDouble("amount");
        Double fee = $paylog.getDouble("fee");
        if ($refund_fee > fee){
            return ResultMsg.fail("退款金额大于支付金额");
        }

        if (empty($refund_fee)) {
            return ResultMsg.fail("退款金额为0");
        }
        PhpMap $device = findOne("SELECT id, weid, assign_company, region_id FROM ims_shopping_goods WHERE id="+dev_id);
        if (empty($device)) {
            return ResultMsg.fail("关联设备不存在");
        }

        Integer $uni_no = 0;

        Integer $rv = 0;

        Integer plid = 0;
        if (!empty($refund_log)) {

            $uni_no = $refund_log.getInt("id");
            $refund_fee = $refund_log.getDouble("amount");

        } else {

            $rv = refund_condition_check($device, $paylog, $refund_fee,false,$gloable);
            if ($rv != 1){
                return ResultMsg.fail("账户余额不足,<br>请确认运营商/合伙人账户有足够余额可以原路退款");
            }

            plid = $paylog.get("plid");
            $gloable.put("plid",plid);
            $rv = refund_condition_check($device, $paylog, $refund_fee, true,$gloable);

            //WeUtility::logging('refund '. $rv. ',' . $refund_tab);

            PhpMap $refund_update = new PhpMap();
            Integer time = PhpUtil.time();
            $refund_update.put("weid",$operator_uid);
            $refund_update.put("plid",$paylog.getInt("plid"));
            $refund_update.put("amount",$refund_fee);
            $refund_update.put("msg",$_GPC.get("msg"));
            $refund_update.put("createtime",time);




            if (pdo_insert($refund_tab, $refund_update) >0) {

                PhpMap one = findOne("select * from " + $refund_tab + " where weid = " + $operator_uid + " and createtime = " + time);
                $uni_no = one.getInt("id");
            } else {
                return ResultMsg.fail("系统错误");
            }

            String openid = $paylog.get("openid");
            PhpMap $balance = findOne("SELECT id, surplus FROM ims_core_balancelog WHERE weid="+$operator_uid+" AND openid= '"+openid+"'");
//                    array(':uid' => $operator_uid, ':openid' => $paylog['openid']));

            pdo_update("update "+$core_paylog_tab_cur +" set refund_type = 1,refund_id = "+$uni_no+" ,refund_fee = "+$refund_fee+" where plid = "+$paylog.getInt("plid"));

            Integer oper_type = $_GPC.getInt("oper_type");
            if (!empty(oper_type)) {
                if (!empty($balance)) {
                    Double surplus = $balance.getDouble("surplus");
                    if (surplus >= $refund_fee){
                        Integer balanceId = $balance.getInt("id");
                        Double $balance_update = surplus - $refund_fee;
                        pdo_update("update ims_core_balancelog set surplus = "+$balance_update +" where id = "+balanceId);
                    }
                }
            }
        }

        String $refund_url = "http://wetiandi.com/api/refund_process.php?do=refund_act&pwd=wt_10071658";
        //$refund_url = 'http://wetiandi.com/api/refund_process.php?do=refund_act&pwd=wt_10071658';

        String $refund_query_url = "http://wetiandi.com/api/refund_process.php?do=refund_query&pwd=wt_10071658";


        JSONObject $refund_post = new JSONObject();
        $refund_post.put("type",$paylog.get("type"));
        $refund_post.put("fee",$paylog.get("fee"));
        $refund_post.put("refund_fee",$refund_fee);
        $refund_post.put("plid",$paylog.get("plid"));
        $refund_post.put("refund_id",$uni_no);
        $refund_post.put("subject",$_GPC.get("msg"));
        $refund_post.put("tag",$paylog.get("tag"));


        String post = curl_request($refund_url, $refund_post.toString());

        JSONObject $result = JSONObject.parseObject(post);
        String rv = $result.getString("rv");
        if (!"1".equals(rv)){
            post = curl_request($refund_query_url, $refund_post.toString());
             $result = JSONObject.parseObject(post);
            rv = $result.getString("rv");
            if (!"1".equals(rv)){
                post = curl_request($refund_url, $refund_post.toString());
                $result = JSONObject.parseObject(post);
                rv = $result.getString("rv");
            }
        }


        if ("1".equals(rv)) {
            pdo_update("update "+$refund_tab+" set status = 1 where id = "+$uni_no);
            return ResultMsg.success("操作成功");
        }  else {
            String msg1 = $result.getString("msg");
            log.error("refund_postive failed id "+ $uni_no+ ", "+msg1);
            return ResultMsg.fail("操作失败,请重试:"+msg1);
        }

    }

    public Integer refund_condition_check(PhpMap $device, PhpMap $payLog, Double $refund_fee,  boolean $substract,PhpMap $gloable){

        Double $total_fee = $payLog.getDouble("fee");
        if ($refund_fee > $total_fee){

            return 0;
        }


        if ($refund_fee == 0){

            return 0;
        }


        Integer $weid = $device.getInt("weid");
        Integer $region_id = $device.getInt("region_id");
//        $GLOBALS['region_id'] = $region_id;

        if (empty($weid)){
            return 0;
        }

        Integer $total_share = 0;
        Integer plid = $payLog.getInt("plid");
        //检查账单表是否有该订单记录

        //正常应该把分账记录记录在订单表的
        //这里不改动订单表业务从分账记录查询 如果都没有分账记录 再走原来默认逻辑
        //查看本月账单有没有分账记录
        String $core_bill_log_cur = PhpUtil.getBillTable();
        String $sql = "SELECT * FROM "+$core_bill_log_cur+" WHERE `plid`="+plid+" and mode=0";
        List<PhpMap> $shareLog = findList($sql);
        if(empty($shareLog)){
            //本有没有查看上月的表有没有分账记录
            $core_bill_log_cur =  PhpUtil.getBillTableLast();
            $sql = "SELECT * FROM "+$core_bill_log_cur+" WHERE `plid`="+plid+" and mode=0";
            $shareLog = findList($sql);
        }
        Integer $rv = 0;
        if(!empty($shareLog)){
            //company_id, share
            for (PhpMap $item : $shareLog) {
                Integer $company_id = $item.getInt("weid");
                Integer $share = $item.getInt("percent");
                if (empty($share)) {
                    continue;
                }

                Integer $tid = $payLog.getInt("tid");
                if(equals($company_id,$tid)){
                    //自己的账单 忽略
                    continue;
                }

                $total_share += $share;

                $rv = refund_user_surplus_calc($company_id, $share, $refund_fee, $substract,$gloable);
                if ($rv == 0) {
                    return 0;
                }
            }
        }else{
            Integer $assign_company = $device.getInt("assign_company");    //0 no company, 1 multi company, otherwise single company
            if ($assign_company == 1){
                if (!empty($region_id)) {

                    String $company_share_condition = " weid="+$weid+" AND region_id="+$region_id;

                    List<PhpMap> $company_share = findList("SELECT * FROM ims_region_company_share WHERE "+$company_share_condition);
                    for (PhpMap $item : $company_share) {

                        Integer $company_id = $item.getInt("company_id");
                        Integer $share = $item.getInt("share");

                        if (empty($share)) {
                            continue;
                        }


                        $total_share += $share;

                        $rv = refund_user_surplus_calc($company_id, $share, $refund_fee, $substract,$gloable);
                        if ($rv == 0){
                            return 0;
                        }
                    }
                }
            } else {
                if ($assign_company > 1){
                    PhpMap $user = findOne("SELECT uid, precent FROM ims_mc_members WHERE uid="+$assign_company);
                    Integer uid = $user.getInt("uid");
                    if (!empty(uid)){
                        Integer precent = $user.getInt("precent");
                        if (!empty(precent)){
                            Integer $share = precent;
                            $total_share = $share;
                            $rv = refund_user_surplus_calc($assign_company, $share, $refund_fee, $substract,$gloable);
                            if ($rv == 0){
                                return 0;
                            }
                        }
                    }
                }
            }
        }

        if ($total_share > 100){
            return 0;
        }


        if ($total_share == 100){
            return 1;
        }


        Integer $share = 100 - $total_share;

        $rv = refund_user_surplus_calc($weid, $share, $refund_fee, $substract,$gloable);
        if ($rv == 0){
            return 0;
        }

        return 1;
    }

    public Integer refund_user_surplus_calc(Integer $uid, Integer $share, Double $refund_fee, boolean $substract,PhpMap $GLOBALS){

        if (empty($uid)){
            return 0;
        }

        if (empty($share)){
            return 1;
        }

        PhpMap $user = findOne("SELECT uid, surplus FROM ims_mc_members WHERE uid="+$uid);
        if (empty($user)){
            return 0;
        }

        Double $refund_part = $refund_fee * $share / 100;
        Double $surplus = $user.getDouble("surplus");
        if ($surplus < $refund_part){
            return 0;
        }


        if (!$substract){
            return 1;
        }

        $surplus =$surplus - $refund_part;
        pdo_update("update ims_mc_members set surplus = "+$surplus+" where uid = "+$uid);
        Integer plid = $GLOBALS.getInt("plid");
        if(empty(plid)){
            plid = 0;
        }
        Integer region_id = $GLOBALS.getInt("region_id");
        if(empty(region_id)){
            region_id = 0;
        }
        mcBillLog($uid,plid,region_id,"订单退款",1,$refund_part,$share,"");

        return 1;
    }


    //添加用户账单
    public void mcBillLog(Integer $weid,Integer $plid,Integer $regionId,String $type,Integer $mode,Double $amount,Integer $percent,String $remark){
        try{
            PhpMap $log = new PhpMap();
            $log.put("weid", $weid);
            $log.put("plid", $plid);
            $log.put("region_id",$regionId);
            $log.put("type", $type);
            $log.put("mode", $mode);
            $log.put("percent",$percent);
            $log.put("amount", $amount);
            $log.put("remark", $remark);
            $log.put("create_time",  PhpUtil.time());
            String $table = PhpUtil.getBillTable();
            pdo_insert($table, $log);
        }catch (Exception e){
            log.error("分账错误",e);
        }

    }

    public Integer pdo_insert(String table, PhpMap phpMap) {
        StringBuilder colName = new StringBuilder();
        Set<String> cols = phpMap.keySet();
        for (String col : cols) {
            if (colName.length() > 0) {
                colName.append(",");
            }
            colName.append(col);
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        String sql = "insert into " + table + " (" + colName + ") values ";
        StringBuilder curVal = new StringBuilder();
        for (String col : cols) {
            Object object = phpMap.get(col);
            if (curVal.length() > 0) {
                curVal.append(",");
            }
            if (object == null) {
                curVal.append(object);
                continue;
            }
            if (object instanceof Integer) {
                curVal.append(object);
            } else if (object instanceof Date) {
                Date date = (Date) object;
                String format2 = format.format(date);
                curVal.append("'" + format2 + "'");
            } else {
                if (object instanceof String) {
                    String str = (String) object;
                    str = zhuanyiDanyinhao(str);
                    curVal.append("'" + str + "'");
                } else {
                    curVal.append("'" + object + "'");
                }
            }
        }
        String endSql = sql +"("+curVal+")";
        return pdo_update(endSql);
    }

    private static String curl_request(String url,String data){
        return HttpUtil.post(url,data);
    }

    private static String zhuanyiDanyinhao(String str) {
        int length = str.length();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            char c = str.charAt(i);
            if(c == '\'' || c=='\\'){
                sb.append("\\"+c);
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static boolean isEmpty(Object value) {
        if (value == null) {
            return true;
        }

        if (value instanceof String) {
            return ((String) value).trim().isEmpty();
        } else if (value instanceof Collection) {
            return ((Collection) value).isEmpty();
        } else if (value instanceof Map) {
            return ((Map) value).isEmpty();
        } else if(value instanceof PhpMap){
            return ((PhpMap) value).isEmpty();
        } else if(value instanceof Number){
           Number data = (Number) value;
            int i = data.intValue();
            return i == 0;
        }else {
            return false;
        }
    }


    private boolean empty(Object key){
        return isEmpty(key);
    }



    private List<PhpMap> findList(String sql){
        List<Map<String, Object>> maps = tDeviceRecordMapper.selectCommonSql(sql);
        if(maps.isEmpty()){
            return new ArrayList<>();
        }
        List<PhpMap> list = new ArrayList<>();
        for (Map<String, Object> map : maps) {
            PhpMap phpMap = new PhpMap();
            Set<String> strings = map.keySet();
            for (String key : strings) {
                phpMap.put(key,map.get(key));
            }
            list.add(phpMap);
        }

        return list;


    }

    private Integer pdo_update(String sql){
       return tDeviceRecordMapper.updateCommonSql(sql);
    }

    private PhpMap findOne(String sql){
        List<Map<String, Object>> maps = tDeviceRecordMapper.selectCommonSql(sql);
        if(maps.isEmpty()){
            return new PhpMap();
        }
        PhpMap phpMap = new PhpMap();
        Map<String, Object> map = maps.get(0);
        Set<String> strings = map.keySet();
        for (String key : strings) {
            phpMap.put(key,map.get(key));
        }
        return phpMap;


    }

    public static boolean equals(Integer value,Integer val2){
        if(value == null || val2 == null){
            return false;
        }

        return value.equals(val2);
    }

}
